/*
 * 本代码是用来进行串口解析默认为Arduino平台 可移植至其他平台
 * 本代码中 用Serial.print作为串口输出 若非Arduino平台，更换成相应UART函数输出即可
 */
#include "cmd.h"
#include "FOC/FOC.h"
#include "BAT/BAT.h"
cmdNode cmd_list[CMD_LIST_SIZE];
static int cmd_state = 0;
extern FOC::sMotor Motor_CH1, Motor_CH2;
extern BAT::sBatUnit batUnit;
void cmdThread(void *pvParameters) // This is a task.
{
  (void)pvParameters;
  Serial.println("cmd Thread running success\n");
  Serial.println("You can use 'help' to get all available command!");
  
  while (1)
  {
    CMD::getCMD();
    switch (cmd_state)
    {
    case 1:
        FOC::LOG();
        break;
    case 2:
        Serial.print(Motor_CH1.act_speed);
        Serial.print('\t');
        Serial.print(Motor_CH1.A);
        Serial.print('\t');
        Serial.print(Motor_CH1.B);
        Serial.print('\t');
        Serial.println(Motor_CH1.C);
        break;
    case 3:
        Serial.print(Motor_CH2.act_speed);
        Serial.print('\t');
        Serial.print(Motor_CH2.A);
        Serial.print('\t');
        Serial.print(Motor_CH2.B);
        Serial.print('\t');
        Serial.println(Motor_CH2.C);
        break;
    case 4:
        Serial.println(batUnit.Vol);
    default:
        break;
    }
    
    vTaskDelay(20);
  }
}
/*help命令*/
int cmd_help(void){
    for (int i = 0; i < CMD_LIST_SIZE; i++)
    {
        if (strcmp(cmd_list[i].cmd_name,""))//根据名字查找
        {
            Serial.print(cmd_list[i].cmd_name);
            Serial.print("\t----\t");
            Serial.println(cmd_list[i].cmd_message);
        }
    }
    return 0;
}

/*用户自定义函数区*/

int log(void){
    cmd_state = 1;
    Serial.println("enable log OK!");
    return 0;
}
int dislog(void){
    cmd_state = 0;
    Serial.println("disable log OK!");
    return 0;
}
int CH1(void){
    cmd_state = 2;
    Serial.println("show CH1 encoder info OK!");
    return 0;
}
int CH2(void){
    cmd_state = 3;
    Serial.println("show CH2 encoder info OK!");
    return 0;
}
int batVolLog(void){
    cmd_state = 4;
    Serial.println("fast_reverse OK!");
    return 0;
}
int restart(void){
    esp_restart();
    return 0;
}
/*用户初始化 注册cmd处*/
void CMD::init(void){
    /*命令在此添加*/
    
    CMD::Register("help"        ,"function describe" ,&cmd_help          ,0);//cmd名称 cmd描述信息 cmd函数指针 哈希地址(需不同)
    CMD::Register("log"         ,"enable FOC info"   ,&log              ,1);//cmd名称 cmd描述信息 cmd函数指针 哈希地址(需不同)
    CMD::Register("dislog"      ,"disable FOC info"  ,&dislog              ,2);//cmd名称 cmd描述信息 cmd函数指针 哈希地址(需不同)
    CMD::Register("CH1"         ,"CH1 encoder info"  ,&CH1              ,3);//cmd名称 cmd描述信息 cmd函数指针 哈希地址(需不同)
    CMD::Register("CH2"         ,"CH2 encoder info"  ,&CH2      ,4);//cmd名称 cmd描述信息 cmd函数指针 哈希地址(需不同)
    CMD::Register("BAT"         ,"Battery Vol info"  ,&batVolLog      ,5);//cmd名称 cmd描述信息 cmd函数指针 哈希地址(需不同)
    // cmd_register("fast_r"       ,"fast_reverse"     ,&fast_reverse      ,5);//cmd名称 cmd描述信息 cmd函数指针 哈希地址(需不同)
    CMD::Register("restart"      ,"restart Mcu"      ,&restart           ,6);//cmd名称 cmd描述信息 cmd函数指针 哈希地址(需不同)
    xTaskCreatePinnedToCore(
      cmdThread, "cmdThread", 2048,
      NULL, 1, NULL,
      1);
}


/*系统函数区 用户无需关心 记得更改Serial.print输出函数即可*/

void CMD::getCMD(void){
    String serial_recv_buffer = Serial.readString();
    if (serial_recv_buffer != "")
    {
      CMD::parsing((char *)serial_recv_buffer.c_str());
    }
}

void CMD::Register(const char cmd_name[CMD_LENGTH],const char cmd_message[CMD_MESSAGE_LENGTH],cmd_handler func_name,int hash_node){
    strcpy(cmd_list[hash_node].cmd_name,cmd_name);
    strcpy(cmd_list[hash_node].cmd_message,cmd_message);
    cmd_list[hash_node].hander = func_name;
    cmd_list[hash_node].node_hash = hash_node;

}
//查询函数 若用户追求时间复杂度 则可自行优化 hash值
void CMD::parsing(char name[CMD_LENGTH]){
    if(name[0] != '\n')name = strtok(name,"\n");//去除回车符
    else{
        Serial.print("\n");//接受空cmd时进行换行
        return ;
        }
    for (int i = 0; i < CMD_LIST_SIZE; i++)
    {
        if (!strcmp(cmd_list[i].cmd_name,name))//根据名字查找
        {
            cmd_list[i].hander();
            return ;
        }
    }
    Serial.println("not found cmd!\nYou can use 'help' to get all available command!");//可自行换成串口输出
}